//! @file   lc_thread.h
//! @brief  
//! @author Sayan Chaliha
//! @date   September, 2011
//!
//! 
#ifndef _LC_THREAD_H
#define _LC_THREAD_H

#include "libcyan_internal.h"
#include "lc_types.h"
#include "lc_condition_variable.h"
#include "lc_multi_reader_lock.h"
#include "lc_thread_storage.h"
#include "lc_object.h"

namespace cyan {
  class CYAN_API Thread : public Object {
  public:        
    enum Scope {
      SCOPE_GLOBAL = THREAD_SCOPE_GLOBAL,
      SCOPE_LOCAL = THREAD_SCOPE_LOCAL
    };

    enum Priority {
      PRIORITY_LOWEST,
      PRIORITY_LOW,
      PRIORITY_NORMAL,
      PRIORITY_HIGH,
      PRIORITY_HIGHEST
    };

    enum State {
      STATE_JOINABLE = THREAD_STATE_JOINABLE,
      STATE_DETACHED = THREAD_STATE_DETACHED
    };

    Thread(Scope = SCOPE_GLOBAL, State = STATE_JOINABLE,
    Priority = PRIORITY_NORMAL, Size = 0);

    void start();
    void cancel();
    void clearCancellation();
    Bool testCancellation() const;
    void join();
    void detach();
    Scope scope() const;
    Priority priority() const;
    void priority(Priority);
    State state() const;
    Bool isStarted() const;
    Bool isRunning() const;

  protected:
    virtual ~Thread();

  private:
    enum Execution {
      EXECUTION_START_PENDING,
      EXECUTION_STARTED,
      EXECUTION_JOIN_PENDING
    };

    Thread(const Thread&);
    void operator =(const Thread&);

    Bool CYAN_HIDDEN isJoinPending() const;
    static void CYAN_HIDDEN startPoint(void*);
    virtual void process() = 0;
    Bool CYAN_HIDDEN threadStart();
    void CYAN_HIDDEN threadEnd();
    static Int CYAN_HIDDEN priorityMap(Int, Priority);
    static Priority CYAN_HIDDEN priorityMap(Int, Int);

    mutable Mutex executionLock_;
    ConditionVariable startCondition_;
    Execution execution_;

    mutable Strobe cancelCondtion_;

    State currentState_;
    mutable MultiReaderLock threadGuard_;

    ThreadAttributesType threadAttributes_;
    ThreadHandleType threadHandle_;

    static ThreadStorage<Thread*> CYAN_HIDDEN threadRef_;
  };
}
#endif /* _LC_THREAD_H */
